require 'json'
require 'active_support/core_ext'

module Dor
  class SearchService

    RISEARCH_TEMPLATE = "select $object from <#ri> where $object <dc:identifier> '%s'".freeze
    @@index_version = nil

    class << self

      def index_version
        Dor::VERSION
      end

      def risearch(query, opts = {})
        client = Config.fedora.client['risearch']
        client.options[:timeout] = opts.delete(:timeout)
        query_params = {
          :type   => 'tuples',
          :lang   => 'itql',
          :format => 'CSV',
          :limit  => '1000',
          :stream => 'on',
          :query  => query
        }.merge(opts)
        result = client.post(query_params)
        result.split(/\n/)[1..-1].collect { |pid| pid.chomp.sub(/^info:fedora\//, '') }
      end

      def iterate_over_pids(opts = {}, &block)
        opts[:query] ||= 'select $object from <#ri> where $object <info:fedora/fedora-system:def/model#label> $label'
        opts[:in_groups_of] ||= 100
        opts[:mode] ||= :single
        start = 0
        pids = Dor::SearchService.risearch("#{opts[:query]} limit #{opts[:in_groups_of]} offset #{start}")
        while pids.present?
          if opts[:mode] == :single
            pids.each { |pid| yield pid }
          else
            yield pids
          end
          start += pids.length
          pids = Dor::SearchService.risearch("#{opts[:query]} limit #{opts[:in_groups_of]} offset #{start}")
        end
      end

      def query(query, args = {})
        params = args.merge({ :q => query })
        params[:start] ||= 0
        resp = solr.find params
        return resp unless block_given?
        cont = true
        while cont && resp.docs.length > 0
          cont = yield(resp)
          params[:rows] ||= resp.docs.length
          params[:start] += params[:rows]
          resp = solr.find params
        end
      end

      def query_by_id(id)
        if id.is_a?(Hash) # Single valued: { :google => 'STANFORD_0123456789' }
          id = id.collect { |*v| v.join(':') }.first
        elsif id.is_a?(Array) # Two values: [ 'google', 'STANFORD_0123456789' ]
          id = id.join(':')
        end
        q = %(#{Solrizer.solr_name 'identifier', :stored_searchable}:"#{id}")
        result = []
        query(q, :fl => 'id', :rows => 1000) do |resp|
          result += resp.docs.collect { |doc| doc['id'] }
          true
        end
        result
      end

      def solr
        @@solr ||= ActiveFedora.solr.conn.is_a?(RSolr::Client) ? ActiveFedora.solr.conn : Dor::Config.make_solr_connection
      end

      # @return String druid of the SDR Graveyard APO
      #   nil if APO does not exist in the currently configured environment
      def sdr_graveyard_apo_druid
        @@sdr_graveyard_apo ||= find_sdr_graveyard_apo_druid
      end

      def find_sdr_graveyard_apo_druid
        r = Dor::SearchService.query('dc_title_tesim:"SDR Graveyard"', :fl => 'id')
        if r.docs.empty?
          nil
        else
          r.docs.first[:id]
        end
      end

    end

  end
end
